package com.mdd.admin.service.category.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mdd.admin.service.category.IGoodsCategoryService;
import com.mdd.admin.validate.category.GoodsCategoryParam;
import com.mdd.admin.vo.category.GoodsCategoryDetailVo;
import com.mdd.admin.vo.category.GoodsCategoryListVo;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.entity.goods.GoodsCategory;
import com.mdd.common.entity.goods.Goods;
import com.mdd.common.enums.RecommendEnum;
import com.mdd.common.enums.ShowEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.category.GoodsCategoryMapper;
import com.mdd.common.mapper.goods.GoodsMapper;
import com.mdd.common.utils.TimeUtil;
import com.mdd.common.utils.UrlUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 服务分类实现类
 */
@Service
public class GoodsCategoryServiceImpl extends ServiceImpl<GoodsCategoryMapper, GoodsCategory> implements IGoodsCategoryService {

    @Resource
    GoodsCategoryMapper goodsCategoryMapper;

    @Resource
    private GoodsMapper goodsMapper;

    /**
     * 服务分类列表
     *
     * @param params    搜索参数
     * @return PageResult<GoodsCategoryListVo>
     */
    @Override
    public List<GoodsCategoryListVo> list(Map<String, String> params) {
        QueryWrapper<GoodsCategory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_delete", GlobalConstant.NOT_DELETE);
        queryWrapper.eq("pid", 0);
        queryWrapper.orderByDesc("sort");
        queryWrapper.orderByAsc("create_time");

        goodsCategoryMapper.setSearch(queryWrapper, params, new String[]{
                "like:name:str",
                "=:pid:long",
                "=:level:int",
                "=:image:str",
                "=:sort:int",
                "=:isShow@is_show:int",
                "=:isRecommend@is_recommend:int",
        });

        List<GoodsCategory> goodsCategories = goodsCategoryMapper.selectList(queryWrapper);
        List<GoodsCategoryListVo> list = new LinkedList<>();
        List<Long> pidIds = goodsCategories.stream().map(GoodsCategory::getId).distinct().collect(Collectors.toList());
        List<GoodsCategory> pidGoods = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(pidIds)) {
            LambdaQueryWrapper<GoodsCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(GoodsCategory::getPid, pidIds);
            lambdaQueryWrapper.eq(GoodsCategory::getIsDelete, GlobalConstant.NOT_DELETE);
            pidGoods = goodsCategoryMapper.selectList(lambdaQueryWrapper);
        }
        Map<Long, List<GoodsCategory>> pidGroupGoodsMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(pidGoods)) {
            pidGroupGoodsMap = pidGoods.stream().collect(Collectors.groupingBy(GoodsCategory::getPid));
        }
        Map<Integer, String> recommendMap = RecommendEnum.getMap();
        Map<Integer, String> showMap = ShowEnum.getMap();
        for (GoodsCategory item : goodsCategories) {
            GoodsCategoryListVo vo = new GoodsCategoryListVo();
            BeanUtils.copyProperties(item, vo);
            vo.setImage(UrlUtil.toAbsoluteUrl(item.getImage()));
            vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            vo.setIsRecommendName(recommendMap.get(vo.getIsRecommend()));
            vo.setIsShowName(showMap.get(vo.getIsShow()));
            if (pidGroupGoodsMap.containsKey(item.getId())) {
                List<GoodsCategory> categoryList = pidGroupGoodsMap.get(item.getId());
                List<GoodsCategoryListVo> sons = Lists.newArrayList();
                for (GoodsCategory category : categoryList) {
                    GoodsCategoryListVo son = new GoodsCategoryListVo();
                    BeanUtils.copyProperties(category, son);
                    son.setImage(UrlUtil.toAbsoluteUrl(category.getImage()));
                    son.setIsRecommendName(recommendMap.get(son.getIsRecommend()));
                    son.setIsShowName(showMap.get(son.getIsShow()));
                    son.setCreateTime(TimeUtil.timestampToDate(category.getCreateTime()));
                    son.setUpdateTime(TimeUtil.timestampToDate(category.getUpdateTime()));
                    sons.add(son);
                }
                vo.setSons(sons);
            }
            list.add(vo);
        }
        return list;
    }

    /**
     * 服务分类详情
     *
     * @param id 主键参数
     * @return GoodsCategory
     */
    @Override
    public GoodsCategoryDetailVo detail(Long id) {
        GoodsCategory model = goodsCategoryMapper.selectOne(
                new QueryWrapper<GoodsCategory>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在");
        GoodsCategoryDetailVo vo = new GoodsCategoryDetailVo();
        BeanUtils.copyProperties(model, vo);
        vo.setIsShowName(ShowEnum.getMap().get(vo.getIsShow()));
        vo.setIsRecommendName(RecommendEnum.getMap().get(vo.getIsRecommend()));
        vo.setImage(UrlUtil.toAbsoluteUrl(model.getImage()));
        return vo;
    }

    /**
     * 服务分类新增
     *
     * @param goodsCategoryParam 参数
     */
    @Override
    public void add(GoodsCategoryParam goodsCategoryParam) {
        String name = goodsCategoryParam.getName();
        LambdaQueryWrapper<GoodsCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsCategory::getName, name);
        lambdaQueryWrapper.eq(GoodsCategory::getIsDelete, GlobalConstant.NOT_DELETE);
        lambdaQueryWrapper.last("limit 1");
        GoodsCategory category = super.getOne(lambdaQueryWrapper);
        Assert.isNull(category, "此分类名称已存在,请重新输入!");
        GoodsCategory model = new GoodsCategory();
        model.setName(goodsCategoryParam.getName());
        model.setPid(goodsCategoryParam.getPid());
        model.setLevel(goodsCategoryParam.getLevel());
        model.setImage(UrlUtil.toRelativeUrl(goodsCategoryParam.getImage()));
        model.setSort(goodsCategoryParam.getSort());
        model.setIsShow(goodsCategoryParam.getIsShow());
        model.setIsRecommend(goodsCategoryParam.getIsRecommend());
        model.setCreateTime(TimeUtil.timestamp());
        model.setUpdateTime(TimeUtil.timestamp());
        goodsCategoryMapper.insert(model);
    }

    /**
     * 服务分类编辑
     *
     * @param goodsCategoryParam 参数
     */
    @Override
    public void edit(GoodsCategoryParam goodsCategoryParam) {
        GoodsCategory model = goodsCategoryMapper.selectOne(
                new QueryWrapper<GoodsCategory>()
                        .eq("id", goodsCategoryParam.getId())
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");
        if (goodsCategoryParam.getId().equals(goodsCategoryParam.getPid())) {
            throw new OperateException("不能选择自己作为父级");
        }

        model.setId(goodsCategoryParam.getId());
        model.setName(goodsCategoryParam.getName());
        model.setPid(goodsCategoryParam.getPid());
        model.setLevel(goodsCategoryParam.getLevel());
        model.setImage(UrlUtil.toRelativeUrl(goodsCategoryParam.getImage()));
        model.setSort(goodsCategoryParam.getSort());
        model.setIsShow(goodsCategoryParam.getIsShow());
        model.setIsRecommend(goodsCategoryParam.getIsRecommend());
        model.setUpdateTime(TimeUtil.timestamp());
        goodsCategoryMapper.updateById(model);
        if (goodsCategoryParam.getPid() == 0) {
            List<GoodsCategory> list = goodsCategoryMapper.selectList(
                    new QueryWrapper<GoodsCategory>()
                            .eq("pid", goodsCategoryParam.getId()));
            if (CollectionUtils.isEmpty(list)) {
                return;
            }
            for (GoodsCategory goodsCategory : list) {
                goodsCategory.setIsRecommend(goodsCategoryParam.getIsRecommend());
                goodsCategory.setUpdateTime(TimeUtil.timestamp());
                goodsCategoryMapper.updateById(goodsCategory);
            }
        }
    }

    /**
     * 服务分类删除
     *
     * @param id 主键ID
     */
    @Override
    public void del(Long id) {
        GoodsCategory model = goodsCategoryMapper.selectOne(
                new QueryWrapper<GoodsCategory>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        LambdaQueryWrapper<Goods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Goods::getCategoryId, id);
        lambdaQueryWrapper.eq(Goods::getIsDelete, GlobalConstant.NOT_DELETE);
        lambdaQueryWrapper.last("limit 1");
        Goods goods = goodsMapper.selectOne(lambdaQueryWrapper);
        Assert.isNull(goods, "服务分类正在使用中,无法删除");
        model.setDeleteTime(TimeUtil.timestamp());
        model.setIsDelete(GlobalConstant.DELETE);
        goodsCategoryMapper.updateById(model);
    }

    @Override
    public List<GoodsCategoryListVo> listPid() {
        LambdaQueryWrapper<GoodsCategory> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(GoodsCategory::getPid, GlobalConstant.DEFAULT_GOODS_PID);
        lambdaQueryWrapper.eq(GoodsCategory::getIsDelete, GlobalConstant.NOT_DELETE);
        List<GoodsCategory> list = goodsCategoryMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        List<Long> pidIds = list.stream().map(GoodsCategory::getId).distinct().collect(Collectors.toList());
        Map<Long, List<GoodsCategory>> groupMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(pidIds)) {
            LambdaQueryWrapper<GoodsCategory> sonLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sonLambdaQueryWrapper.in(GoodsCategory::getPid, pidIds);
            sonLambdaQueryWrapper.eq(GoodsCategory::getIsDelete, GlobalConstant.NOT_DELETE);
            List<GoodsCategory> sonList = goodsCategoryMapper.selectList(sonLambdaQueryWrapper);
            groupMap = sonList.stream().collect(Collectors.groupingBy(GoodsCategory::getPid));
        }

        Map<Integer, String> recommendMap = RecommendEnum.getMap();
        Map<Integer, String> showMap = ShowEnum.getMap();
        List<GoodsCategoryListVo> targetList = Lists.newArrayList();
        for (GoodsCategory goodsCategory : list) {
            GoodsCategoryListVo vo = new GoodsCategoryListVo();
            BeanUtils.copyProperties(goodsCategory, vo);
            vo.setIsShowName(showMap.get(vo.getIsShow()));
            vo.setIsRecommendName(recommendMap.get(vo.getIsRecommend()));
            vo.setImage(UrlUtil.toAbsoluteUrl(goodsCategory.getImage()));
            vo.setCreateTime(TimeUtil.timestampToDate(goodsCategory.getCreateTime()));
            vo.setUpdateTime(TimeUtil.timestampToDate(goodsCategory.getUpdateTime()));
            if (groupMap.containsKey(goodsCategory.getId())) {
                List<GoodsCategoryListVo> sonList = Lists.newArrayList();
                List<GoodsCategory> categoryList = groupMap.get(goodsCategory.getId());
                for (GoodsCategory category : categoryList) {
                    GoodsCategoryListVo sonVo = new GoodsCategoryListVo();
                    BeanUtils.copyProperties(category, sonVo);
                    sonVo.setImage(UrlUtil.toAbsoluteUrl(category.getImage()));
                    sonVo.setIsShowName(showMap.get(sonVo.getIsShow()));
                    sonVo.setIsRecommendName(recommendMap.get(sonVo.getIsRecommend()));
                    sonList.add(sonVo);
                }
                vo.setSons(sonList);
            }
            targetList.add(vo);
        }
        return targetList;
    }

    @Override
    public void updateStatus(Long id, Integer isShow) {
        GoodsCategory goodsCategory = goodsCategoryMapper.selectById(id);
        Assert.notNull(goodsCategory, "数据不存在");
        goodsCategory.setId(id);
        goodsCategory.setIsShow(isShow);
        goodsCategory.setUpdateTime(TimeUtil.timestamp());
        goodsCategoryMapper.updateById(goodsCategory);
    }

    @Override
    public List<GoodsCategory> listByIds(List<Long> categoryIds) {
        if (CollectionUtils.isEmpty(categoryIds)) {
            return Lists.newArrayList();
        }
        return super.listByIds(categoryIds);
    }

}
